package com.bc004346.travelus.services;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.os.SystemClock;

import com.bc004346.travelus.CheckinActivity;
import com.bc004346.travelus.R;
import com.bc004346.travelus.dataAccess.SQLHelper;
import com.bc004346.travelus.model.domain.Flight;
import com.bc004346.travelus.model.domain.NotificationParameters;
import com.bc004346.travelus.model.domain.Reservation;
import com.bc004346.travelus.utility.NotificationHelper;

import java.util.ArrayList;
import java.util.Date;

import static com.bc004346.travelus.utility.Utility.DAY;
import static com.bc004346.travelus.utility.Utility.log;

/**
 * Created by Renats on 11/14/2014.
 * This monitors user flights and will push a notification when it is time to checkin
 */
public class CheckinService extends Service {

    private SQLHelper mSqlHelper;
    public static final String CHECKIN_INTENT = "com.bc004346.travelus.services.CheckinService";
    private PendingIntent mPendingCheckinIntent;
    public static final String EXTRA_FLIGHT = "FLIGHT";
    private BroadcastReceiver mBroadcastCheckinReceiver;
    private AlarmManager mAlarmManager;

    public SQLHelper getSqlHelper() {
        if (mSqlHelper == null) {
            mSqlHelper = new SQLHelper(getApplicationContext());
        }
        return mSqlHelper;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        log("starting");
        try {
            ArrayList<Reservation> reservations = getSqlHelper().selectReservations();
            mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            setupAsyncCheckin();

            if (reservations.size() > 0)
                for (Reservation res : reservations)
                    for (Flight flight : res.getFlights()) {
                        if (flight.isCheckedIn()) continue;

                        long timeSpan = flight.getDeparture().getTime() - new Date().getTime();
                        log(String.format(getString(R.string.dashboardLog_ScheduleCheckIn),
                                flight, String.valueOf(flight.isCheckedIn()), timeSpan));

                        if (timeSpan <= DAY)
                            doCheckin(flight);

                        else if (timeSpan > DAY && timeSpan < DAY * 7)
                            scheduleCheckin(flight, timeSpan - DAY);
                    }
        } catch (Exception e) {
            log(e);
        }

        return Service.START_STICKY;
    }

    private void doCheckin(Flight flight) {

        try {
            NotificationParameters options = new NotificationParameters(this, flight,
                    CheckinActivity.NOTIFICATION_EXTRA, "Checkin for your flight",
                    "Flight " + flight.toString(),
                    CheckinActivity.class, CheckinActivity.NOTIFICATION_ID);
            NotificationHelper.displayNotification(options);
            flight.setIsCheckInScheduled(true);
            getSqlHelper().UpdateFlight(flight);
        } catch (Exception e) {
            log(e);
        }
    }

    private void scheduleCheckin(Flight flight, long timeSpan) {

        try {
            log(String.format(getString(R.string.dashboardLog_ScheduleCheckInDate),
                    flight.toString(),
                    (int) timeSpan,
                    new Date(new Date().getTime() + timeSpan)));

            Intent intent = new Intent(CHECKIN_INTENT);
            intent.putExtra(EXTRA_FLIGHT, flight);

            mPendingCheckinIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                    SystemClock.elapsedRealtime() + timeSpan,
                    mPendingCheckinIntent);

            flight.setIsCheckInScheduled(true);
            getSqlHelper().UpdateFlight(flight);

        } catch (Exception e) {
            log(e);
        }
    }

    private void setupAsyncCheckin() {
        if (mBroadcastCheckinReceiver == null) {
            mBroadcastCheckinReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    Flight flight = (Flight) intent.getSerializableExtra(EXTRA_FLIGHT);
                    doCheckin(flight);
                }
            };
            registerReceiver(mBroadcastCheckinReceiver, new IntentFilter(CHECKIN_INTENT));
        }
    }

    @Override
    public void onDestroy() {
        mAlarmManager.cancel(mPendingCheckinIntent);

        if (mBroadcastCheckinReceiver != null)
            unregisterReceiver(mBroadcastCheckinReceiver);

        super.onDestroy();
    }
}
